/*
    Copyright 2006-2011 Patrik Jonsson, sunrise@familjenjonsson.org

    This file is part of Sunrise.

    Sunrise is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    Sunrise is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Sunrise.  If not, see <http://www.gnu.org/licenses/>.

*/

/** \file

    Declaration of the Mcrx class, which handles most of the
    functionality for mcrx. \ingroup mcrx */

// $Id$

#ifndef __mcrx__
#define __mcrx__

#include "preferences.h"
#include "mcrx-units.h"
#include "mcrx-types.h"
#include <string>
#include "boost/thread/thread.hpp"
#include "random.h"
#include "terminator.h"
#include "monitor.h"

/// Namespace for the CCfits classes.
namespace CCfits {
  class FITS;
  class ExtHDU;
}

class binifstream;
class binofstream;


/// Namespace for the Sunrise classes.
namespace mcrx {
  class Mcrx;
  class mcrx_terminator;

  typedef local_random mcrx_rng_policy;
}

/** This class is responsible for the overall mcrx run. It sets up the
    configuration according to the input file and runs the successive
    stages. \ingroup mcrx */
class mcrx::Mcrx {
private:
public:
  Preferences p; ///< Preferences object with configuration data.
  T_unit_map units; ///< The units used.
  /// The random-number generator state saved between the stages.
  std::vector<T_rng::T_state> rng_states;  
  /// Signal from sentry indicating that exit is requested.
  mcrx::terminator::t_type t;
  class file_sentry;
  class time_sentry;
  monitor mon_;
  boost::thread monitor_thread_;
  
  void initialize_output_file ();
  void setup_units();
  void write_parameters (CCfits::FITS&) const;
  void setup_emergence (CCfits::FITS&);
  void write_history (CCfits::HDU&) const;
  T_float load_lost_energy (CCfits::ExtHDU&, int) const;
  void write_lost_energy (CCfits::ExtHDU&, T_float, T_float, int) const;
  void load_rng_states (CCfits::FITS&);
  void load_rng_states (binifstream&);
  void write_rng_states (CCfits::FITS&);
  void write_rng_states (binofstream&);
  
  bool generate_integrated_SED ();
  void calc_deposition_fraction(CCfits::FITS&, const std::vector<T_float>&,
				const array_1&, const std::vector<long>&,
				const std::vector<bool>&, 
				array_1&) const;
  array_1 calculate_L_absorbed(CCfits::FITS& output);
  bool calculate_attenuated_images();
  void get_dust_template (T_float, array_1&, array_1&);
  bool add_infrared_templates ();
  void execute_adaptive_stages();
  void execute_arepo_stages();
  void execute_stages();
public:
  Mcrx (const Preferences& pp): p (pp), t (terminator::false_) {};
  ~Mcrx() {};

  mcrx::terminator::t_type terminator () const {return t;};
  void kill () {t = mcrx::terminator::true_;};
  void restart () {t = mcrx::terminator::restart_;};
  
  // constants
  const static std::string sllec, slrlc, slnc, slnrc;
};


/// Terminator class that looks at the Mcrx terminator. \ingroup mcrx
class mcrx::mcrx_terminator: public terminator {
public:
  Mcrx& m;
  mcrx_terminator (Mcrx& mm): m (mm) {};
  virtual t_type operator() () const {return m.terminator();};
};

/** Thread class for termination file checking.  This thread looks for
    a file named "mcrx_terminate" and if it finds it, sets the
    terminator. \ingroup mcrx */
class mcrx::Mcrx::file_sentry {
private:
  Mcrx* self;
public:
  file_sentry (Mcrx* m): self (m) {};

  void operator () ();
};

/** Thread for time limit checking.  This thread checks on CPU and
    wall clock time limits and if they are running out, sets the
    terminator. \ingroup mcrx */
class mcrx::Mcrx::time_sentry {
private:
  Mcrx* self;
  const time_t start;
  int wall_limit;
  int cpu_margin; 
  int wall_margin;
  bool dump_on_exit;
public:
  time_sentry (Mcrx* m, int cm, int wm);
  /** Copy constructor transfers dump_on_exit to child but sets it to
      false in this, so we don't get multiple outputs. */
  time_sentry (const time_sentry& rhs) : 
    self(rhs.self), start (rhs.start), wall_limit(rhs.wall_limit),
    cpu_margin(rhs.cpu_margin), wall_margin(rhs.wall_margin),
    dump_on_exit(rhs.dump_on_exit) {dump_on_exit=false;};

  ~time_sentry () { if(dump_on_exit) print_used(); };

  void operator () ();
  void print_used() const;
};


class dummy_cell{
public:
  class cell_tracker {};
  class cell_tracker_info {};
};

class dummy_grid{
public:
  typedef dummy_cell T_cell;
  typedef void T_data;
};



#endif

// doxygen main page definition

/*! \mainpage Sunrise Monte-Carlo Radiative Transfer
\section intro_sec Introduction

Sunrise is a Monte-Carlo Radiative Transfer code that can be used to
calculate absorption and scattering of radiation in a medium of
arbitrary geometry, defined on an adaptive-mesh grid.  These grids are
generated from hydrodynamic N-body simulation outputs or through a
"factory class" where arbitrary code can be used.  It can also operate
on an unstructured Voronoi mesh if support for the hydro code Arepo is
enabled. The main functionality of Sunrise consists of 3 executables.
This is the documentation of the code, automatically generated using
Doxygen.

Sunrise is free software, available under the terms of the GNU General
Public License. The Sunrise web site is
http://sunrise.familjenjonsson.org.

*/



